package net.sanative.system
{
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.filesystem.File;
    import flash.filesystem.FileMode;
    import flash.filesystem.FileStream;
    import flash.net.URLRequest;
    import flash.net.URLStream;
    import flash.desktop.NativeApplication;
    import flash.desktop.Updater;
    import flash.utils.ByteArray;
    
    import mx.controls.Alert;
    import mx.events.CloseEvent;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.http.HTTPService;
   
    public class UpdateManager extends EventDispatcher{
        public var versionURL:String;
        
        public var isUpdate:Boolean = false;
        
        public var isLoaded:Boolean = false;
        
        private var appXml:XML = NativeApplication.nativeApplication.applicationDescriptor;
        
        private var currentVersion:String = appXml.@version;
        
        private var version:XML;
        
        private var urlStream:URLStream;
        
        private var fileData:ByteArray = new ByteArray();
        
        private var versionService:HTTPService;
       
        public function UpdateManager(vURL:String):void{
            versionURL = vURL;
            loadRemoteFile();
        }
            
        // load the remote version.xml file
        private function loadRemoteFile():void{
            versionService = new HTTPService();
            versionService.url = this.versionURL;
            versionService.useProxy=false;
            versionService.method = "GET";
            versionService.resultFormat="xml";
            versionService.send();
            versionService.addEventListener(ResultEvent.RESULT, testVersion);
        }
       
        /*
        test the currentVersion against the remote version file and either alert the user of
        an update available or force the update
        */
        public function testVersion(event:ResultEvent):void{
          version = XML(event.result);
          versionService.removeEventListener(ResultEvent.RESULT, testVersion);
          
          if(version.@forceUpdate != undefined) {
	          isLoaded = true;
	          if((currentVersion != version.@version) && version.@forceUpdate == true){
	              getUpdate();
	          }else if(currentVersion != version.@version){
	                Alert.show("There is an update available,\nwould you like to get it now? \n\nDetails:\n" + version.@message, "Choose Yes or No", 3, null, alertClickHandler);
	          }
          } else {
          	dispatchEvent(new Event("updaterComplete"));
          }
        }   
       
        /*
        test the currentVersion against the remote version file and either alert the user of
        an update available or force the update, if no update available, alert user
        */
        public function checkForUpdate():Boolean{
          if(version  ==  null){
            this.loadRemoteFile();
            return true;
          }
          
          if((currentVersion != version.@version) && version.@forceUpdate == true){
              getUpdate();
          }else if(currentVersion != version.@version){
                Alert.show("There is an update available,\nwould you like to get it now? \n\nDetails:\n" + version.@message, "Choose Yes or No", 3, null, alertClickHandler);
          }else{
              Alert.show("There are no new updates available", "NOTICE");
          }
          return true;
        }
       
        // handle the Alert window decission
        private function alertClickHandler(event:CloseEvent):void {
            if (event.detail==Alert.YES){
                getUpdate();
            }
        }
       
        // get the new version from the remote server
        public function getUpdate():void{
        	dispatchEvent(new Event("isUpdating"));
            var urlReq:URLRequest = new URLRequest(version.@downloadLocation);
            urlStream = new URLStream();
            urlStream.load(urlReq);
            urlStream.addEventListener(Event.COMPLETE, loaded);
        }
        
        // read in the new AIR package
        private function loaded(event:Event):void {
            urlStream.readBytes(fileData, 0, urlStream.bytesAvailable);
            urlStream.removeEventListener(Event.COMPLETE, loaded);
            writeAirFile();
        }
       
        // write the newly downloaded AIR package to the application storage directory
        private function writeAirFile():void {
            var file:File = File.applicationStorageDirectory.resolvePath("Update.air");
            var fileStream:FileStream = new FileStream();
            fileStream.addEventListener(Event.CLOSE, fileClosed);
            fileStream.openAsync(file, FileMode.WRITE);
            fileStream.writeBytes(fileData, 0, fileData.length);
            fileStream.close();
        }
        
        // after the write is complete, call the update method on the Updater class
        private function fileClosed(event:Event):void {
        	var updater:Updater = new Updater();
          	var airFile:File = File.applicationStorageDirectory.resolvePath("Update.air");
          	updater.update(airFile,version.@version);
        }
       
    }
}